package io.litchi.common.anno.mysql.handler;

import io.litchi.common.anno.mysql.QuerySql;
import io.litchi.common.anno.mysql.canstant.QueryMode;
import org.springframework.data.jpa.domain.Specification;

import jakarta.persistence.criteria.*;

import java.lang.reflect.Field;
import java.util.*;

/**
 *
 *
 * @author helang
 * @since 2025-11-13
 */
public class QueryUtil {
    /**
     * 构建动态查询条件
     *
     * @param param 查询参数对象（DTO），字段需标注 @QuerySql
     * @param <T>   实体类型
     * @return Specification 条件构建器
     */
    public static <T> Specification<T> buildQueryJpa( Object param,Class<T> clazz) {
        if (param == null) {
            return (root, query, cb) -> cb.conjunction(); // 无条件 → true
        }

        return (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            Class<?> paramClass = param.getClass();
            Field[] fields = getAllFields(paramClass);

            for (Field field : fields) {
                QuerySql querySql = field.getAnnotation(QuerySql.class);
                if (querySql == null) continue;

                field.setAccessible(true);
                try {
                    Object value = field.get(param);
                    if (shouldSkip(value)) continue; // 跳过空值

                    String entityField = querySql.value();
                    QueryMode mode = querySql.queryMode();

                    Predicate predicate = buildPredicate(cb, root, entityField, value, mode);
                    if (predicate != null) {
                        predicates.add(predicate);
                    }
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("无法读取字段: " + field.getName(), e);
                }
            }

            if (predicates.isEmpty()) {
                return cb.conjunction(); // 无条件 → 返回 true
            }
            return cb.and(predicates.toArray(new Predicate[0]));
        };
    }

    // 获取类及其父类的所有字段
    private static Field[] getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        while (clazz != null && clazz != Object.class) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass();
        }
        return fields.toArray(new Field[0]);
    }

    // 判断是否应跳过该值（null、空字符串、空集合）
    private static boolean shouldSkip(Object value) {
        if (value == null) return true;
        if (value instanceof String && ((String) value).isBlank()) return true;
        if (value instanceof Collection && ((Collection<?>) value).isEmpty()) return true;
        if (value instanceof Map && ((Map<?, ?>) value).isEmpty()) return true;
        if (value.getClass().isArray() && java.lang.reflect.Array.getLength(value) == 0) return true;
        return false;
    }

    // 构建单个 Predicate
    private static Predicate buildPredicate(
            CriteriaBuilder cb,
            Root<?> root,
            String entityField,
            Object value,
            QueryMode mode) {

        Path<Object> path = root.get(entityField); // 支持嵌套字段，如 "dept.name"

        switch (mode) {
            case EQ:
                return cb.equal(path, value);
            case NE:
                return cb.notEqual(path, value);
            case LIKE:
                if (value instanceof String str) {
                    return cb.like(cb.lower(path.as(String.class)), "%" + str.toLowerCase() + "%");
                }
                break;
            case GT:
                if (value instanceof Comparable comp) {
                    return cb.greaterThan(path.as(Comparable.class), comp);
                }
                break;
            case GE:
                if (value instanceof Comparable comp) {
                    return cb.greaterThanOrEqualTo(path.as(Comparable.class), comp);
                }
                break;
            case LT:
                if (value instanceof Comparable comp) {
                    return cb.lessThan(path.as(Comparable.class), comp);
                }
                break;
            case LE:
                if (value instanceof Comparable comp) {
                    return cb.lessThanOrEqualTo(path.as(Comparable.class), comp);
                }
                break;
            case IN:
                if (value instanceof Iterable<?> iterable) {
                    return path.in(iterable);
                } else if (value.getClass().isArray()) {
                    return path.in((Object[]) value);
                }
                break;
            case NOT_IN:
                if (value instanceof Iterable<?> iterable) {
                    return cb.not(path.in(iterable));
                } else if (value.getClass().isArray()) {
                    return cb.not(path.in((Object[]) value));
                }
                break;
            case IS_NULL:
                return cb.isNull(path);
            case IS_NOT_NULL:
                return cb.isNotNull(path);
            case BETWEEN:
                if (value instanceof List<?> list && list.size() == 2) {
                    Comparable<?> start = (Comparable<?>) list.get(0);
                    Comparable<?> end = (Comparable<?>) list.get(1);

                    Path<Object> path_ = root.get(entityField);
                    Expression expr = path_.as(Object.class);
                    Expression startExpr = cb.literal(start);
                    Expression endExpr = cb.literal(end);

                    return cb.and(
                            cb.greaterThanOrEqualTo(expr, startExpr),
                            cb.lessThanOrEqualTo(expr, endExpr)
                    );
                }
                break;
            default:
                return cb.equal(path, value);
        }
        return null; // 不支持的类型或模式，忽略
    }
    
}